package logic.file;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

import logic.FileSystemFactory;
import logic.NotExistingFileException;
import logic.UnsupportedProtocol;
import logic.operation.ByteCounter;

//TODO raczej kompozycja na klasie bazowej wyprowadzonej z klasy abstrakcyjnej implementującej interfejs IFIle
public class LocalDirectory extends LocalFile implements IDirectory {
	
	static Logger logger = Logger.getLogger(LocalDirectory.class.getName());
	
	List<String> fileList = new ArrayList<String>();
	
	long dirSize = 0;

	public LocalDirectory(String path) {			//spr., ale najlepiej by byl prawdop. dotep pakietowy, 
													//instancjonowanie tylko przez fabryke
		super(path);
		//logger.debug("FILE:" + file);
		if (file.list() != null) {
			fileList = Arrays.asList(file.list());			//fileList do wywalenia użycie zamiast tego za każdym razem listFile()
		}
	}

	@Override
	public Iterator<IFile> iterator() {
		return listFiles().iterator();
	}

	@Override
	public List<String> getFiles() {
		return fileList;
	}

	@Override
	public int getFilesCount() throws UnsupportedProtocol {
		return listFiles().size();
	}	
	
	public String toString() {
		return fileList.toString();
	}

	@Override
	public String getFile(int index) {
	// TODO Auto-generated method stub
		return null;
	}
	
	@Override
	public long getSize() {
		return dirSize;
	}

	@Override
	public List<IFile> listFiles() {
		if (file.canRead()) {
			String [] fileNames = file.list();
			List<IFile> dirList = new ArrayList<IFile>();
			for (String name : fileNames) {
				//TODO łapanie wyjątku spowodowanego brakiem odpowiednich praw dostępu, nie ma uprawnien do found000 trzeba to zlapac wczesniej
				try {
					dirList.add( FileSystemFactory.getElement(file.getAbsolutePath(), name) );
				} catch (UnsupportedProtocol e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (NotExistingFileException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}			//TODO tutaj dodonie specjalnego folderu, ktory bedzie przenosil katalog wyzej
			return dirList;
		} else {
			return null;
		}
	}
	
	//dwie wersje potrzebne by każde obliczenie wielkości folderu nie zmianiało widoku, a w Javie nie ma parametrów domyślnych
	//to jest wywoływane gdy chcemy zmienić widok
	@Override
	public long calcDirSize() {
		return calcDirSize(true);
	}
	
	/*
	 * (non-Javadoc)
	 * @see logic.file.IDirectory#calcDirSize(boolean)
	 * Gdy save jest równy false funkcja nie zmieni wartości przechowywanej w obiekcie. 
	 * Przydatne gdy obiekt jest podpięty do jakiegoś widoku np. tabeli.
	 */
	@Override
	public long calcDirSize(boolean save) {		//metoda pokazuje koniecznosc klasy abstrakcyjnej dla Directory, 
									//implementujacej interfejs IDirectory oraz definiującej funkcje 
									//operujące na funkcjach zdefiniowanych w ramach interfejsu
									//TODO ew. wersja iteracyjna - rekurencja nie jest najbezpiecznijeszym wyjsciem
		List<IFile> filesInDir = listFiles();
		long sizeSum = 0;
		for (IFile file : filesInDir) {
			if (!(file instanceof IDirectory)) {
				sizeSum += file.getSize();
			} else {
				sizeSum += ( (IDirectory) file).calcDirSize();
			}
		}
		if (save) {
			dirSize = sizeSum;
		}
		return sizeSum;
	}
	
	@Override
	public void copyTo(String path) throws IOException {
		copyTo(path, null);
	}
	
	@Override
	public void copyTo(String path, ByteCounter bc) throws IOException {
		List<IFile> files = listFiles();
		logger.debug("MDKIR path" + System.getProperty("file.separator") + this.getName());
		new File(path + System.getProperty("file.separator") + this.getName()).mkdir();
		for (IFile file : files) {
			file.copyTo(path + System.getProperty("file.separator") + this.getName(), bc);
		}
	}
	
	public void mkdir() {
		logger.debug("MKDIR" + file.getPath());
		file.mkdir();
	}
	
	//'unit testing'
	public static void main(String[] args) {
		LocalDirectory dir = new LocalDirectory("/java");
		long calculatedSize = dir.calcDirSize();
		assert calculatedSize == 84971320309L : "calculated = " + calculatedSize;								//-ea jvm
	}
	

}
